package com.xyz.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.xyz.controller.vo.InStockVO;
import com.xyz.dto.PartInnStockDto;
import com.xyz.entity.mapper.*;
import com.xyz.entity.pojo.*;
import com.xyz.request.PartInnOrderRequest;
import com.xyz.request.PartInnStockRequest;
import com.xyz.service.PartInnStockService;
import com.xyz.util.ExcelUtils;
import com.xyz.util.dto.DataResult;
import com.xyz.util.dto.GridData;
import com.xyz.util.dto.LoginInfo;
import com.xyz.vo.PartInnOrderDetailVO;
import com.xyz.vo.PartInnOrderVO;
import com.xyz.vo.PartInnStockVO;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;


@Service
@Slf4j
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
public class PartInnStockServiceImpl implements PartInnStockService {

    private final PartInnStockMapper partInnStockMapper;

    private final PartInnOrderMapper partInnOrderMapper;

    private final PartInnOrderDetailMapper partInnOrderDetailMapper;

    private final SystemParameterMapper systemParameterMapper;

    private final SystemEmployeeMapper systemEmployeeMapper;

    private final PartApplyMapper partApplyMapper;

    private final PartInfoMapper partInfoMapper;


    @Override
    public Map<Long, PartInnStock> getPartInnStockByPartIdList(List<Long> partIdList) {
        Map<Long, PartInnStock> partMap = new HashMap<>();
        List<PartInnStock> partInnStocks = partInnStockMapper.selectByPartIdList(partIdList);
        if (CollUtil.isEmpty(partInnStocks)) {
            return partMap;
        }
        // 将查询结果转换为Map
        for (PartInnStock partInnStock : partInnStocks) {
            partMap.put(partInnStock.getPartId(), partInnStock);
        }
        return partMap;
    }

    @Override
    @SneakyThrows
    public void export(PartInnStockRequest param, HttpServletResponse response) {
        List<PartInnStockDto> partInnStockDtoList = partInnStockMapper.selectPartInnList(param.getParam());
        List<PartInnStockVO> partInnStockList = BeanUtil.copyToList(partInnStockDtoList, PartInnStockVO.class);
        ExcelUtils.write(response, "内库出入库记录.xls", "内库出入库记录", PartInnStockVO.class, partInnStockList);
    }

    @Override
    @SneakyThrows
    @Transactional(rollbackFor = Exception.class)
    public DataResult importExcel(LoginInfo li, MultipartFile file) {
        List<PartInnStockVO> read = ExcelUtils.read(file, PartInnStockVO.class);
        if (CollUtil.isNotEmpty(read)) {
           return createInStockByImport(li, read);
        }
        return DataResult.build9200("内库excel导入失败");
    }

    @Override
    @SneakyThrows
    public void innStockExport(PartInnOrderRequest param, HttpServletResponse response) {
        List<PartInnOrder> partInnOrders = getPartInnOrders(param);
        List<PartInnOrderVO> partInnOrderVOList = BeanUtil.copyToList(partInnOrders, PartInnOrderVO.class);
        partInnOrderVOList.forEach(item -> {
            if (ObjectUtil.equals(item.getInnOrderType(), 0)) {
                item.setInnOrderTypeStr("入库");
            } else if (ObjectUtil.equals(item.getInnOrderType(), 1)) {
                item.setInnOrderTypeStr("出库");
            }
        });
        ExcelUtils.write(response, "内库出入库记录.xls", "内库出入库记录", PartInnOrderVO.class, partInnOrderVOList);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public DataResult createInStock(LoginInfo li, List<InStockVO> inStockVOList) {
        List<Long> partIdList = inStockVOList.stream().map(InStockVO::getPartId).collect(Collectors.toList());
        List<PartInnStock> partInnStocks = partInnStockMapper.selectByPartIdList(partIdList);
        Date date = new Date();
        PartInnOrder partInnOrder = new PartInnOrder();
        partInnOrder.setInnOrderCode("SP-INN_BJRK-" + DateUtil.format(date, "yyyyMMdd") + "-" + getPartCode("PART_INN_ORDER"));
        partInnOrder.setInnOrderType(0);
        partInnOrder.setBusinessCode("");
        partInnOrder.setInOutType(0);
        partInnOrder.setOperationEmployeeId(li.getLoginEmployeeId());
        partInnOrder.setOperationTime(date);
        partInnOrder.setApplyId(0L);
        partInnOrder.setBusinessId(0L);
        partInnOrderMapper.insert(partInnOrder);

        for (InStockVO inStockVO : inStockVOList) {
            PartInnStock partInnStock = findPartInnStocks(partInnStocks, inStockVO.getPartId());
            if (partInnStock == null) {
                partInnStock = new PartInnStock();
                partInnStock.setPartId(inStockVO.getPartId());
                partInnStock.setStock(inStockVO.getStock());
                partInnStock.setIsDelete(0);
                partInnStockMapper.insert(partInnStock);
            } else {
                partInnStock.setStock(partInnStock.getStock() + inStockVO.getStock());
                partInnStockMapper.updateStockByPk(partInnStock);
            }

            PartInnOrderDetail partInnOrderDetail = new PartInnOrderDetail();
            partInnOrderDetail.setPartId(inStockVO.getPartId());
            partInnOrderDetail.setInnOrderId(partInnOrder.getId());
            partInnOrderDetail.setInOutNum(inStockVO.getStock());
            partInnOrderDetailMapper.insert(partInnOrderDetail);
        }

        return DataResult.build9100("OK");
    }

    @Override
    public DataResult selectList(LoginInfo li, PartInnStockRequest param) {
        Page<PartInnStockDto> page = PageHelper.startPage(param.getPage(), param.getSize());
        List<PartInnStockDto> partInnStockDtoList = partInnStockMapper.selectPartInnList(param.getParam());
        return DataResult.build9100(new GridData(page.getTotal(), partInnStockDtoList));
    }

    @Override
    public DataResult selectStockOutRecordList(LoginInfo li, PartInnOrderRequest param) {
        Page<PartInnOrder> page = PageHelper.startPage(param.getPage(), param.getSize());
        List<PartInnOrder> partInnOrders = getPartInnOrders(param);
        return DataResult.build9100(new GridData(page.getTotal(), partInnOrders));
    }

    private List<PartInnOrder> getPartInnOrders(PartInnOrderRequest param) {
        List<PartInnOrder> partInnOrders = partInnOrderMapper.selectPartInnOrders(param);
        if (CollUtil.isNotEmpty(partInnOrders)) {
            List<Long> emIdList = partInnOrders.stream().map(PartInnOrder::getOperationEmployeeId).collect(Collectors.toList());
            SystemEmployeeExample seExample = new SystemEmployeeExample();
            seExample.createCriteria().andIsDeleteEqualTo(0).andIdIn(emIdList);
            List<SystemEmployee> systemEmployees = systemEmployeeMapper.selectByExample(seExample);
            Map<Long, String> systemEmployeeMap = systemEmployees.stream().collect(Collectors.toMap(SystemEmployee::getId, SystemEmployee::getEmployeeName, (key1, key2) -> key1));
            partInnOrders.forEach(item -> item.setEmployeeName(systemEmployeeMap.getOrDefault(item.getOperationEmployeeId(), null)));
        }
        return partInnOrders;
    }

    @Override
    public DataResult selectStockOutRecordInfo(LoginInfo li, Long id) {
        if (ObjectUtil.isEmpty(id)) {
            return DataResult.build9200("id不能为空");
        }
        PartInnOrder partInnOrder = partInnOrderMapper.selectPartInnOrdersById(id);
        if (ObjectUtil.isNotEmpty(partInnOrder)) {
            PartApply partApply = partApplyMapper.selectByPrimaryKey(partInnOrder.getApplyId());
            Optional.ofNullable(partApply).ifPresent(item -> partInnOrder.setApplyCode(item.getApplyCode()));

            List<PartInnOrderDetailVO> partInnOrderDetailList = partInnOrderDetailMapper.selectOutNum(id);
            partInnOrder.setPartInnOrderDetailList(partInnOrderDetailList);

            SystemEmployee systemEmployee = systemEmployeeMapper.selectByPrimaryKey(partInnOrder.getOperationEmployeeId());
            Optional.ofNullable(systemEmployee).ifPresent(item -> partInnOrder.setEmployeeName(systemEmployee.getEmployeeName()));
        }
        return DataResult.build9100(partInnOrder);
    }

    private PartInnStock findPartInnStocks(List<PartInnStock> partInnStocks, Long partId) {
        for (PartInnStock partInnStock : partInnStocks) {
            if (partInnStock.getPartId().equals(partId)) {
                return partInnStock;
            }
        }
        return null;

    }


    private String getPartCode(String key) {
        SystemParameter sp = systemParameterMapper.selectByPrimaryKey(key);
        int num = Integer.parseInt(sp.getParameterValue()) + 1;
        String code;
        if (num < 10) {
            code = "000" + num;
        } else if (num < 100) {
            code = "00" + num;
        } else if (num < 1000) {
            code = "0" + num;
        } else {
            code = "" + num;
        }
        sp.setParameterValue(num + "");
        systemParameterMapper.updateByPrimaryKey(sp);
        return code;
    }

    public DataResult createInStockByImport(LoginInfo li, List<PartInnStockVO> innStockVoList) {
        List<String> code = innStockVoList.stream().map(PartInnStockVO::getCode).collect(Collectors.toList());
        PartInfoExample partInfoExample = new PartInfoExample();
        partInfoExample.createCriteria().andIsDeleteEqualTo(0).andCodeIn(code);
        List<PartInfo> partInfoList = partInfoMapper.selectByExample(partInfoExample);
        Map<String, PartInfo> partInfoMap = partInfoList.stream().collect(Collectors.toMap(PartInfo::getCode, thisObjects -> thisObjects, (key1, key2) -> key1));
        Map<Long, PartInnStock> partInnStockMap = getPartInnStockByPartIdList(partInfoList.stream().map(PartInfo::getId).collect(Collectors.toList()));
        for (PartInnStockVO importInnStockVo : innStockVoList) {
            PartInfo partInfo = partInfoMap.get(importInnStockVo.getCode());
            if (partInfo != null) {
                PartInnStock partInnStock = partInnStockMap.get(partInfo.getId());
                if (partInnStock == null) {
                    partInnStock = new PartInnStock();
                    partInnStock.setPartId(partInfo.getId());
                    partInnStock.setStock(importInnStockVo.getStock());
                    partInnStock.setIsDelete(0);
                    partInnStockMapper.insert(partInnStock);
                } else {
                    partInnStock.setStock(partInnStock.getStock() + importInnStockVo.getStock());
                    partInnStockMapper.updateStockByPk(partInnStock);
                }

                PartInnOrder partInnOrder = new PartInnOrder();
                partInnOrder.setInnOrderCode("SP-INN_BJRK-" + DateUtil.format(new Date(), "yyyyMMdd") + "-" + getPartCode("PART_INN_ORDER"));
                partInnOrder.setInnOrderType(0);
                partInnOrder.setBusinessCode("");
                partInnOrder.setInOutType(0);
                partInnOrder.setOperationEmployeeId(li.getLoginEmployeeId());
                partInnOrder.setOperationTime(new Date());
                partInnOrder.setApplyId(0L);
                partInnOrder.setBusinessId(0L);
                partInnOrderMapper.insert(partInnOrder);

                PartInnOrderDetail partInnOrderDetail = new PartInnOrderDetail();
                partInnOrderDetail.setPartId(partInfo.getId());
                partInnOrderDetail.setInnOrderId(partInnOrder.getId());
                partInnOrderDetail.setInOutNum(importInnStockVo.getStock());
                partInnOrderDetailMapper.insert(partInnOrderDetail);
            }
        }
        return DataResult.build9100("OK");
    }


}
